package com.runen.infinitemovement.service;

import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.runen.infinitemovement.Constant;
import com.runen.infinitemovement.R;
import com.runen.infinitemovement.activity.LockScreenActivity;
import com.runen.infinitemovement.model.entity.GpsDataEntity;
import com.runen.infinitemovement.model.enums.ActivityCompat;
import com.runen.infinitemovement.tool.ActivityUtils;
import com.runen.infinitemovement.tool.CommonUtil;
import com.runen.infinitemovement.tool.MapUtils;
import com.runen.infinitemovement.track.recorduitl.HealthUtil;
import com.runen.rxnetlibrary.utils.JsonUtils;
import com.runen.rxnetlibrary.utils.LogUtil;

import io.reactivex.annotations.Nullable;


/**
 * 循环播放一段无声音频，以提升进程优先级
 * <p>
 * Created by jianddongguo on 2017/7/11.
 * http://blog.csdn.net/andrexpert
 */

public class LocationService extends Service {
    /**
     * 运动通知栏
     */
    private SportsNotification notification;
    private int sportsType;
    static long usedTime;
    long startTime;
    private long pathId;
    private String sportRecordId;
    private final static String TAG = "locationService";
    private AMapLocationClient mLocationClient;
    private AMapLocationClientOption mLocationOption;
    private MediaPlayer mMediaPlayer;
    private PowerManager pm;
    private PowerManager.WakeLock wakeLock = null;

    public static final int MSG_LOCK_SCREEN_FROM_CLIENT = 100;

    private AudioManager mAudioManager;

    private AudioManager.OnAudioFocusChangeListener mAudioFocusChange = new
            AudioManager.OnAudioFocusChangeListener() {
                @Override
                public void onAudioFocusChange(int focusChange) {
                    switch (focusChange) {
                        case AudioManager.AUDIOFOCUS_GAIN:
                            Log.e(TAG, "AUDIOFOCUS_GAIN");
                            try {
                                startPlayMusic();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            break;
                        case AudioManager.AUDIOFOCUS_LOSS:
                            Log.e(TAG, "AUDIOFOCUS_LOSS");
                            mAudioManager.abandonAudioFocus(mAudioFocusChange);
                            break;
                        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                            Log.e(TAG, "AUDIOFOCUS_LOSS_TRANSIENT");
                            break;
                        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                            Log.e(TAG, "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
                            break;
                    }
                }
            };
    //发送消息，用来和Service之间传递步数
    private Messenger messenger = new Messenger(new MessengerHandler());
    //广播接收
    private BroadcastReceiver myReceiver;
    //2秒进行一次发送
    private static int saveDuration = 2000;
    //自定义简易计时器
    private TimeCount timeCount;
    private AMapLocation sendMapLocation;
    private GpsDataEntity mGpsDataEntity;
    private boolean isPause;

    /**
     * 自定义handler
     */
    private class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case Constant.MSG_SPORTS_FROM_CLIENT:
                    try {
                        Bundle bundleReserve = msg.getData();
                        usedTime = bundleReserve.getLong("myTime");
                        isPause = bundleReserve.getBoolean("myIsPause");
                        mDistance = bundleReserve.getDouble("distance");
                        sportsType = bundleReserve.getInt("SPORTS_TYPE");
                        sportRecordId = bundleReserve.getString("sportRecordId");
//                        Intent intent = new Intent();
//                        intent.putExtra("userTime", usedTime);
//                        intent.putExtra("distance", mDistance);
//                        intent.putExtra("isPause", isPause);
//                        intent.setAction("com.runen.lockScreen");
//                        sendBroadcast(intent);
                        //这里负责将当前的步数发送出去，可以在界面或者其他地方获取，我这里是在MainActivity中获取来更新界面
                        if (null != sendMapLocation) {
                            if (sendMapLocation.getLocationType() != 6) {//过滤掉基站定位
                                Messenger messenger = msg.replyTo;
                                Message replyMsg = Message.obtain(null, Constant.MSG_SPORTS_FROM_SERVER);
                                Bundle bundle = new Bundle();
                                bundle.putString("AMapLocation", JsonUtils.toJson(sendMapLocation));
                                bundle.putString("GpsDataEntity", JsonUtils.toJson(mGpsDataEntity));
                                bundle.putLong("userTime", usedTime);
                                bundle.putDouble("distance", mDistance);
                                replyMsg.setData(bundle);
                                messenger.send(replyMsg);
                            }
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                case MSG_LOCK_SCREEN_FROM_CLIENT:
                    try {
                        //这里负责将当前的步数发送出去，可以在界面或者其他地方获取，我这里是在MainActivity中获取来更新界面
                        Log.e("123456", "handleMessage: MSG_LOCK_SCREEN_FROM_CLIENT");
                        Messenger messenger = msg.replyTo;
                        Message replyMsg = Message.obtain(null, LockScreenActivity.MSG_REPLY);
                        Bundle bundle = new Bundle();
                        bundle.putLong("userTime", usedTime);
                        bundle.putDouble("distance", mDistance);
                        bundle.putBoolean("isPause", isPause);
                        replyMsg.setData(bundle);
                        messenger.send(replyMsg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                        Log.e("123456", "handleMessage: " + e.getMessage());
                    }
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }

    @SuppressLint("WakelockTimeout")
    @Override
    public void onCreate() {
        super.onCreate();
        initBroadcastReceiver();

        startTimeCount();
        pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LocationService.class.getName());
        wakeLock.acquire();
        if (Constant.DEBUG) {
            Log.d(TAG, TAG + "---->onCreate,启动服务");
        }
        mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
        if (mAudioManager != null)
            mAudioManager.requestAudioFocus(mAudioFocusChange, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);

        mMediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.no_notice);
        mMediaPlayer.setLooping(true);

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
//        mHandler.sendEmptyMessage(1);
        Settings.System.putInt(this.getContentResolver(), Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_NEVER);
        notification = new SportsNotification(this);
        notification.setContentIntent(PendingIntent.getBroadcast(this, 0, getStatusIntent(), PendingIntent.FLAG_UPDATE_CURRENT));
        startForeground(notification.getNotificationId(), notification.getNotification());
        new Thread(new Runnable() {
            @Override
            public void run() {
                startPlayMusic();
                startLocation();
            }
        }).start();

        return START_STICKY;
    }


    /**
     * 初始化广播
     */
    private void initBroadcastReceiver() {
        final IntentFilter filter = new IntentFilter();
        // 屏幕灭屏广播
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        //关机广播
        filter.addAction(Intent.ACTION_SHUTDOWN);
        // 屏幕解锁广播
        filter.addAction(Intent.ACTION_USER_PRESENT);
        // 当长按电源键弹出“关机”对话或者锁屏时系统会发出这个广播
        // example：有时候会用到系统对话框，权限可能很高，会覆盖在锁屏界面或者“关机”对话框之上，
        // 所以监听这个广播，当收到时就隐藏自己的对话，如点击pad右下角部分弹出的对话框
        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        //监听日期变化
        filter.addAction(Intent.ACTION_DATE_CHANGED);
        filter.addAction(Intent.ACTION_TIME_CHANGED);
        filter.addAction(Intent.ACTION_TIME_TICK);

        myReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                switch (action) {
                    // 屏幕灭屏广播
                    case Intent.ACTION_SCREEN_OFF:
                        //屏幕熄灭改为10秒一存储
                        saveDuration = 2000;
                        Intent startIntent = new Intent(context, LockScreenActivity.class);
                        startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startIntent.putExtra(ActivityCompat.USER_TIME, usedTime);
                        context.startActivity(startIntent);
                        break;
                    case Intent.ACTION_SCREEN_ON:
                        saveDuration = 2000;
                        break;
                    //关机广播，保存好当前数据
                    case Intent.ACTION_SHUTDOWN:
                        saveDuration = 2000;
                        break;
                    // 屏幕解锁广播
                    case Intent.ACTION_USER_PRESENT:
                        saveDuration = 2000;
                        ActivityUtils.getInstance().finishActivity(LockScreenActivity.class);
                        break;
                    // 当长按电源键弹出“关机”对话或者锁屏时系统会发出这个广播
                    // example：有时候会用到系统对话框，权限可能很高，会覆盖在锁屏界面或者“关机”对话框之上，
                    // 所以监听这个广播，当收到时就隐藏自己的对话，如点击pad右下角部分弹出的对话框
                    case Intent.ACTION_CLOSE_SYSTEM_DIALOGS:
                        saveDuration = 2000;
                        break;
                    //监听日期变化
                    case Intent.ACTION_DATE_CHANGED:
                    case Intent.ACTION_TIME_CHANGED:
                    case Intent.ACTION_TIME_TICK:
                        saveDuration = 2000;
                        break;
                    default:
                        break;
                }
            }
        };
        //注册广播
        registerReceiver(myReceiver, filter);
    }

    /**
     * 启动定位
     */
    void startLocation() {
        stopLocation();

        if (null == mLocationClient) {
            mLocationClient = new AMapLocationClient(this);
        }

        mLocationOption = new AMapLocationClientOption();
//        mLocationOption.setGpsFirst(true);
        // 使用连续
        mLocationOption.setOnceLocation(false);
        mLocationOption.setLocationCacheEnable(false);
        // 每2秒定位一次
        mLocationOption.setInterval(2 * 1000);
        // 地址信息
        mLocationOption.setNeedAddress(true);
        //设置是否使用传感器。默认是false
        mLocationOption.setSensorEnable(true);
//        mLocationOption.setMockEnable(true);
        //设置高精度模式
        if (CommonUtil.judgeNetIsConnected()) {
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        } else {
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Device_Sensors);
        }
        //设置是否gps优先，只在高精度模式下有效。默认关闭
        mLocationOption.setGpsFirst(true);

        mLocationClient.setLocationOption(mLocationOption);
        mLocationClient.setLocationListener(locationListener);
        mLocationClient.startLocation();
    }

    /**
     * 停止定位
     */
    void stopLocation() {
        if (null != mLocationClient) {
            mLocationClient.stopLocation();
        }
    }

    private int locationCount;
    AMapLocationListener locationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation aMapLocation) {
            //发送结果的通知
            sendLocationBroadcast(aMapLocation);
        }


        private void sendLocationBroadcast(AMapLocation aMapLocation) {
            //记录信息并发送广播
            locationCount++;
            long callBackTime = System.currentTimeMillis();
            StringBuffer sb = new StringBuffer();
            sb.append("定位完成 第" + locationCount + "次\n");
            sb.append("回调时间: " + MapUtils.formatUTC(aMapLocation.getTime(), null) + "\n");
            if (null == aMapLocation) {
                sb.append("定位失败：location is null!!!!!!!");
            } else {
                sb.append(MapUtils.getLocationStr(aMapLocation));
            }


            sendMapLocation = aMapLocation;

            mGpsDataEntity = new GpsDataEntity();
            mGpsDataEntity.altitude = aMapLocation.getAltitude();
            mGpsDataEntity.latitude = aMapLocation.getLatitude();
            mGpsDataEntity.longitude = aMapLocation.getLongitude();
            mGpsDataEntity.speed = aMapLocation.getSpeed();
            mGpsDataEntity.course = aMapLocation.getBearing();
            mGpsDataEntity.horizontalAccuracy = aMapLocation.getAccuracy();
            mGpsDataEntity.state = aMapLocation.getGpsAccuracyStatus();
            mGpsDataEntity.timestamp = aMapLocation.getTime();
            mGpsDataEntity.type = aMapLocation.getLocationType();
            mGpsDataEntity.errorCode = aMapLocation.getErrorCode();
//            Intent mIntent = new Intent(SportsStatusActivity.RECEIVER_ACTION);
//            mIntent.putExtra("result", sb.toString());
//            mIntent.putExtra("locationResult", aMapLocation);
            //发送广播
//            sendBroadcast(mIntent);
//            if (sendMapLocation != null && sendMapLocation.getErrorCode() == 0) {
//                if (!isPause) {
//                    isSend = intercept(aMapLocation);
//                    if (!isSend) {
//                        if (aMapLocation.getAccuracy() <= 50) {
//                            moveDistance(aMapLocation);
//                            privLocation = aMapLocation;
//                        }
//                    }
            sendMessageNotify();
//                }
//            }
            LogUtil.e("aMapLocation", sb.toString());
        }

    };


    private void startPlayMusic() {
        if (mMediaPlayer != null) {
            if (Constant.DEBUG)
                Log.d(TAG, "启动后台播放音乐");
            mMediaPlayer.start();
        }
    }

    private void stopPlayMusic() {
        if (mMediaPlayer != null) {
            if (Constant.DEBUG)
                Log.d(TAG, "关闭后台播放音乐");
            mMediaPlayer.stop();
        }

        if (wakeLock != null) {
            wakeLock.release();
            wakeLock = null;
        }
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopPlayMusic();
        stopLocation();
        mDistance = 0;
        usedTime = 0;
        stopForeground(true);
        unregisterReceiver(myReceiver);
        if (Constant.DEBUG)
            Log.d(TAG, TAG + "---->onCreate,停止服务");
//        // 重启自己
//        Intent intent= new Intent(getApplicationContext(), LocationService.class);
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//            startForegroundService(intent);
//        } else {
//            startService(intent);
//        }
    }

    private double mDistance = 0;

    /**
     * 获取运动状态意图
     *
     * @return
     */
    private Intent getStatusIntent() {
        Intent intent = new Intent("ACTION_SPORTS_STATUS");
        intent.setComponent(new ComponentName(LocationService.this, SportsActionReceiver.class.getName()));
        intent.putExtra("SPORTS_TYPE", sportsType);
        intent.putExtra("sportRecordId", sportRecordId);
        return intent;
    }

    /**
     * 发送消息到通知栏
     */
    private void sendMessageNotify() {
        switch (sportsType) {
            case 0:
                notification.setIcon(R.mipmap.ico_run_circel);
                notification.setDistance(mDistance / 1000);
                notification.setCalorie((int) getSportCalorie());
                notification.setTime(usedTime);
                break;
            case 1:
                notification.setIcon(R.mipmap.ico_riding_circel);
                notification.setDistance(mDistance / 1000);
                notification.setCalorie((int) getSportCalorie());
                notification.setTime(usedTime);
                break;
            case 2:
                notification.setIcon(R.mipmap.ico_walking_circel);
                notification.setDistance(mDistance / 1000);
                notification.setCalorie((int) getSportCalorie());
                notification.setTime(usedTime);
                break;
            default:
                throw new IllegalArgumentException("Unknown sports type");
        }
        notification.notifyChanged();
        startForeground(notification.getNotificationId(), notification.getNotification());
        LogUtil.d(TAG, "发送消息到通知栏");
    }

    /**
     * 获取运动卡路里
     *
     * @return
     */
    private double getSportCalorie() {
        switch (sportsType) {
            case 0:
                return HealthUtil.getCalorie(60.0, mDistance / 1000, HealthUtil.K_RUNNING);
            case 1:
                return HealthUtil.getCalorie(60.0, mDistance / 1000, HealthUtil.K_WALKING);
            case 2:
                return HealthUtil.getCalorie(60.0, mDistance / 1000, HealthUtil.K_RIDING);
            default:
                throw new IllegalArgumentException("Unknown sports type");
        }
    }

    /**
     * 开始倒计时，去存发送数据
     */
    private void startTimeCount() {
        timeCount = new TimeCount(saveDuration, 1000);
        timeCount.start();
    }

    private class TimeCount extends CountDownTimer {
        /**
         * @param millisInFuture    The number of millis in the future from the call
         *                          to {@link #start()} until the countdown is done and {@link #onFinish()}
         *                          is called.
         * @param countDownInterval The interval along the way to receive
         *                          {@link #onTick(long)} callbacks.
         */
        public TimeCount(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }

        @Override
        public void onTick(long millisUntilFinished) {

        }

        @Override
        public void onFinish() {
            // 如果计时器正常结束，则每隔三秒存储步数到数据库
            timeCount.cancel();
            startTimeCount();
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}
